﻿using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using UnityEngine;
using UnityEngine.Timeline;

namespace IQIGame.Onigao.Game
{
    public class TimelineAssetInfo : IPoolObject
    {
        public const int RefInfoID = 1;
        public int Id { get; private set; }

        public TimelineAsset asset { get; set; }
        private ResLoader loader { get; set; }
        private List<TimelineEffect> _effects = new List<TimelineEffect>();

        public uint MaxStore => 30;

        public void OnReset()
        {
            this.Clear();
            this.loader?.Put2Pool();
            this.loader = null;
            this.asset = null;
            this.isLoading = false;
            this.AssetName = null;
        }

        public ILinkedListNode Next { get; set; }
        public ILinkedListNode Previous { get; set; }
        public string AssetName { get; set; }
        private float m_LastUseTime;
        public float LastUseTime => m_LastUseTime;
        private bool isLoading { get; set; }
        public bool isLoaded => asset != null;

        public void OnInit(string assetName)
        {
            this.AssetName = assetName;
            this.loader = ResLoader.Create();
        }

        public void OnLoadComplete()
        {
        }

        public void OnGetFromPool()
        {
            this.m_LastUseTime = Time.realtimeSinceStartup;
        }

        public void OnPutBackToPool()
        {
            this.Clear();
        }

        public void OnUpdate(float deltaTime, float unScaledDeltaTime)
        {
        }

        private void Clear()
        {
            this.m_LastUseTime = default;
            this.Id = 0;
            for (int i = 0; i < this._effects.Count; i++)
            {
                var rEffect = this._effects[i];
                rEffect.entity?.EntityGroup.HideEntity(rEffect.entity);
                ClassPool.Put(rEffect);
            }
            this._effects.Clear();
        }

        public void SetId(int entityId)
        {
            Id = entityId;
        }

        public async UniTask<EntityLoadState> Load()
        {
            if (isLoaded)
                return EntityLoadState.CompleteFromPool;
            isLoading = true;
            this.asset = await this.loader.LoadABAssetAwait<TimelineAsset>(AssetName);

            if (this.asset == null)
            {
                isLoading = false;
                return EntityLoadState.Error;
            }
            isLoading = false;
            OnLoadComplete();
            return EntityLoadState.CompleteByLoad;
        }

        public async UniTask<TimelineEffect> FetchEffect(string path)
        {
            // 这里只需要考虑runtime
            var rEffect = ClassPool.Get<TimelineEffect>();
            rEffect.path = path;
            if (!ManagerCenter.Entity.HasEntityGroup(ManagerCenter.Timeline.timelineEffectGroupID))
            {
                ManagerCenter.Entity.EnableGroup(ManagerCenter.Timeline.timelineEffectGroupID);
            }
            rEffect.entity = ManagerCenter.Entity.Get(path, ManagerCenter.Timeline.timelineEffectGroupID);
            this._effects.Add(rEffect);
            await rEffect.entity.Load();
            rEffect.gameObject = rEffect.entity.gameObject;
            return rEffect;
        }

        public void FreeEffect(TimelineEffect effect)
        {
            effect.entity?.EntityGroup.HideEntity(effect.entity);
            ClassPool.Put(effect);
            this._effects.Remove(effect);
        }


        public bool CancelLoading()
        {
            if (!isLoading)
            {
                return false;
            }
            isLoading = false;
            loader.ReleaseAllRes();
            return true;
        }

        public class TimelineEffect : IReusableClass
        {
            public string path;
            public Entity entity;
            public GameObject gameObject;
            public uint MaxStore => 5;

            public void OnReset()
            {
                this.path = default;
                this.gameObject = null;
                this.entity = null;
            }
        }
    }
}